package com.cloud.core.db;

import com.cloud.core.common.utils.reflect.ReflectHelper;
import com.cloud.core.common.utils.reflect.ReflectProp;
import org.apache.log4j.Logger;

import java.util.Map;
import java.util.Objects;

/**
 * Created by cloudy.xie on 17/12/14.
 */
public class SqlProvider {
    private Logger logger = Logger.getLogger(SqlProvider.class);

    public String selectByExample(BaseEntity entity) throws IllegalAccessException {
        StringBuilder sql = getSelectInfo(entity);

        String resultSql = "SELECT * FROM "+entity.getTableName();
        if(sql.length()>4){
            resultSql = "SELECT * FROM "+entity.getTableName()+" where "+sql.substring(5);
        }

        if(entity.getOrderBy()!=null && !Objects.equals(entity.getOrderBy().trim(),"")){
            resultSql +=" order by "+entity.getOrderBy();
        }

        if(entity.getPageSize()!=null && entity.getPageSize()>0){
            resultSql+=" limit "+((entity.getPageCurrent()-1)*entity.getPageSize())+","+entity.getPageSize();
        }
        logger.info(">>>>>>>>>>> selectByExample-sql:"+resultSql);
        return resultSql;
    }

    public String insert(BaseEntity entity) throws IllegalAccessException {
        Map<String, ReflectProp> propMap = ReflectHelper.getReflectProp(entity);
        if (propMap == null || propMap.isEmpty()) {
            throw new RuntimeException();
        }

        StringBuilder sql = new StringBuilder("");
        StringBuilder sqlValue = new StringBuilder("");
        for (Map.Entry<String, ReflectProp> entry : propMap.entrySet()) {
            if (entry.getValue().getValue() == null) continue;

            sql.append(",").append(entry.getKey());
            sqlValue.append(",#{").append(entry.getKey()).append("}");
        }

        if(sql.length()<0){
            throw new RuntimeException();
        }

        String resultSql = "insert into "+entity.getTableName()+"("+sql.substring(1)+")" +
                "values ("+sqlValue.substring(1)+")";
        logger.info(">>>>>>>>>>> insert-sql:"+resultSql);
        return resultSql;
    }

    public String updateByKey(BaseEntity entity) throws IllegalAccessException {
        Map<String, ReflectProp> propMap = ReflectHelper.getReflectProp(entity);
        if (propMap == null || propMap.isEmpty()) {
            throw new RuntimeException();
        }

        StringBuilder sql = new StringBuilder("");
        for (Map.Entry<String, ReflectProp> entry : propMap.entrySet()) {
            if (entry.getValue().getValue() == null) continue;
            sql.append(",").append(entry.getKey()).append("= #{").append(entry.getKey()).append("}");
        }

        String resultSql = "update "+entity.getTableName()+" set "+sql.substring(1);
        if(sql.length()>0){
            resultSql = "update "+entity.getTableName()+" set "+sql.substring(1)+" where id=#{id}";
        }
        logger.info(">>>>>>>>>>> updateByKey-sql:"+resultSql);
        return resultSql;
    }

    public String count(BaseEntity entity) throws IllegalAccessException {
        StringBuilder sql = getSelectInfo(entity);
        String resultSql = "SELECT count(*) FROM "+entity.getTableName();
        if(sql.length()>4){
            resultSql = "SELECT count(*) FROM "+entity.getTableName()+" where "+sql.substring(5);
        }
        logger.info(">>>>>>>>>>> selectByExample-sql:"+resultSql);
        return resultSql;
    }

    private StringBuilder getSelectInfo(BaseEntity entity) throws IllegalAccessException {
        Map<String, ReflectProp> propMap = ReflectHelper.getReflectProp(entity);
        if (propMap == null || propMap.isEmpty()) {
            throw new RuntimeException();
        }

        StringBuilder sql = new StringBuilder("");
        for (Map.Entry<String, ReflectProp> entry : propMap.entrySet()) {
            if (entry.getValue().getValue() == null) continue;

            if (entry.getValue().getType().contains("String")
                    || entry.getValue().getType().contains("char")) {
                sql.append(" and ").append(entry.getKey()).append("='").append(entry.getValue().getValue()).append("'");
            } else if (entry.getValue().getType().contains("boolean") ){
                int value = entry.getValue().getValue().toString().equalsIgnoreCase("true")?1:0;
                sql.append(" and ").append(entry.getKey()).append("=").append(value);
            } else{
                sql.append(" and ").append(entry.getKey()).append("=").append(entry.getValue().getValue());
            }
        }

        return sql;
    }
}
